﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Seagull.Configuration;
using Seagull.DAL.Utils;
using Seagull.Model;
using Seagull.Generic;

namespace Seagull.DAL
{
    /// <summary>
    /// 跨越Segment连续读取帧组，用于<see cref="ReplayController"/>回放。
    /// </summary>
    public class FrameSetReader : IDisposable
    {
        private Segment _currentSegment;
        private readonly PathHelper _pathHelper;
        private Segment _segmentToRead;
        private DateTime _currentReadTime;
        private static readonly int _deltaQuotaMilliseconds = Config.Instance.DataReadConfig.TimestampDeltaQuotaMilliseconds;
        private FrameReader _frameReader;

        private readonly object _syncRoot = new object();

        public FrameSetReader(PathHelper pathHelper, Segment startSegment)
        {
            _pathHelper = pathHelper;
            _segmentToRead = startSegment;
            _currentReadTime = startSegment.StartTime;
        }

        /// <summary>
        /// 持续读取<see cref="FrameSet"/>，若读完当前<see cref="Segment"/>则前进到下一个，
        /// 直到没有更多的Segment可以读取。若文件存在但读取文件错误且重试失败将抛出异常。
        /// </summary>
        /// <returns></returns>
        public FrameSet Read()
        {
            lock(_syncRoot)
            {
                if(_currentSegment != _segmentToRead)
                {
                    _currentSegment = _segmentToRead;
                    // 已经移动到新的文件
                    if(_frameReader != null)
                    {
                        _frameReader.Dispose();
                        _frameReader = null;
                    }
                    if(_currentSegment.StartTime >= DateTime.Now.TruncateToHour())
                    {
                        // 已经到达当前正在写入的文件了
                        _currentSegment = null;
                        return null;
                    }
                    // 打开下一个文件
                    var segmentFile = _pathHelper.GetSegmentFile(_currentSegment);
                    if(segmentFile.Exists)
                    {
                        _frameReader = new FrameReader(
                            FileHelper.Open(segmentFile.OpenRead),
                            _currentSegment.PhaseShifter,
                            FrameDataMinMaxCoercer.Default.Pipe(_currentSegment.ChannelNoiseFilter));
                    }
                }

                // 每一秒是一个FrameSet
                var frameSet = new FrameSet(
                    _currentReadTime, _deltaQuotaMilliseconds,
                    Config.Instance.DataReadConfig.MinDataValue,
                    Config.Instance.DataReadConfig.MaxDataValue,
                    Config.Instance.ChannelConfig[_currentSegment.Channel].NoiseQuota
                    );
                if(_frameReader != null)
                {
                    _frameReader.ReadUntil(frame => !frameSet.TryInclude(frame));
                }
                _currentReadTime = _currentReadTime.AddSeconds(1);

                // 如果时间轴已经超出当前打开的文件，则前进到新文件
                var segment = _currentSegment;
                if(!segment.Contains(_currentReadTime))
                {
                    segment = _currentSegment.Next;
                }
                _segmentToRead = segment;

                // 无论帧组数据是否有效均返回 - 无效帧组自己会返回全0数据
                return frameSet;
            }
        }

        public void Dispose()
        {
            if(_frameReader != null)
            {
                _frameReader.Dispose();
                _frameReader = null;
            }
        }
    }
}
